//
// Created by bill3000 on 2/19/21.
//

#include <unistd.h>

#include "fruit.hpp"
#include "../json/CJsonObject.hpp"
#include "../log/logger.hpp"

int FruitFSM::action_open_cam(Event*){
    cam1 = new cv::VideoCapture();
    cam1->open(200);
    if (!cam1->isOpened()) { // check if we succeeded
        LOG(ERROR, "Couldn't open camera 0 !");
        std::cout << "Couldn't open camera" << std::endl;
        return -1;
    }
    std::cout<< "Get Cam Successful!" << std::endl;
    cam4 = cam3 = cam2 = cam1;

    return 0;
}

int FruitFSM::action_start_conveyor(Event *){
    Message m;

    m.mtype = 400;
    m.data.ctype = 1;
    m.data.param = 2;
    mq->send_message(M03, &m);

    m.mtype = 400;
    m.data.ctype = 1;
    m.data.param = 1;
    mq->send_message(M03, &m);

    return 0;
}

int FruitFSM::action_stop_conveyor(Event *){
    Message m;

    m.mtype = 400;
    m.data.ctype = 2;
    m.data.param = 2;
    mq->send_message(M03, &m);

    m.mtype = 400;
    m.data.ctype = 2;
    m.data.param = 1;
    mq->send_message(M03, &m);

    return 0;
}

int FruitFSM::action_get_cam_param(Event *event){
    Message m;
    m.mtype = 200;
    m.data.ctype = EVENT_GET_CAM_PARAM + 1;
    
    if ((event->param < 1) || (event->param > 4)) {
        std::string ss = "Param error !";
        LOG(WARNING, ss);
        m.data.param = 1;
        strcpy(m.data.extra.sequence, ss.c_str());
        mq->send_message(M01, &m);
        return -1;
    }
    
    m.data.param = 0;
    m.data.extra.cam.camid = event->param;
    cv::VideoCapture *cam = util_get_cam_by_id(event->param);

    m.data.extra.cam.width = (int)cam->get(cv::CAP_PROP_FRAME_WIDTH);
    m.data.extra.cam.height = (int)cam->get(cv::CAP_PROP_FRAME_HEIGHT);
    m.data.extra.cam.F = (float)cam->get(cv::CAP_PROP_FOCUS);
    m.data.extra.cam.ISO = (int)cam->get(cv::CAP_PROP_IOS_DEVICE_EXPOSURE);
    m.data.extra.cam.speed = (int)cam->get(cv::CAP_PROP_ISO_SPEED);
    
    mq->send_message(M01, &m);
    
    return 0;
}

int FruitFSM::action_preview_still_image(Event *event){
    Message m;
    m.mtype = 200;
    m.data.ctype = EVENT_PREVIEW_STILL_IMAGE + 1;
    
    if ((event->param < 1) || (event->param > 4)) {
        std::string ss = "Param error !";
        LOG(WARNING, ss);
        m.data.param = 1;
        strcpy(m.data.extra.sequence, ss.c_str());
        mq->send_message(M01, &m);
        return -1;
    }
    
    m.data.param = 0;
    cv::VideoCapture *cam = util_get_cam_by_id(event->param);

    cv::Mat frame;
    *cam >> frame;
    if (frame.empty()) {
        m.data.param = 1;
        std::string s = "Capture image error !";
        strcpy(m.data.extra.sequence, s.c_str());
        LOG(ERROR, s);
        mq->send_message(M01, &m);
        return -1;
    }

    std::string ss = util_get_now_time_milli_string();
    ss.insert(0, "/intelli/working/");
    ss.append(".jpg");
    cv::imwrite(ss, frame);
    strcpy(m.data.extra.sequence, ss.c_str());
    mq->send_message(M01, &m);
    
    return 0;
}

int FruitFSM::action_preview_moving_image(Event *event){
    Message m;
    m.mtype = 200;
    m.data.ctype = EVENT_PREVIEW_MOVING_IMAGE + 1;
    
    if ((event->param < 1) || (event->param > 4)) {
        std::string ss = "Param error !";
        LOG(WARNING, ss);
        m.data.param = 1;
        strcpy(m.data.extra.sequence, ss.c_str());
        mq->send_message(M01, &m);
        return -1;
    }
    
    m.data.param = 0;
    cv::VideoCapture *cam = util_get_cam_by_id(event->param);

    cv::Mat frame;
    *cam >> frame;
    if (frame.empty()) {
        m.data.param = 1;
        std::string s = "Capture image error !";
        strcpy(m.data.extra.sequence, s.c_str());
        LOG(ERROR, s);
        mq->send_message(M01, &m);
        return -1;
    }

    std::string ss = util_get_now_time_milli_string();
    ss.insert(0, "/intelli/working/");
    ss.append(".jpg");
    cv::imwrite(ss, frame);
    strcpy(m.data.extra.sequence, ss.c_str());
    mq->send_message(M01, &m);

    return 0;
}

int FruitFSM::action_modify_cam_param(Event *event){
    Message m;
    m.mtype = 200;
    m.data.ctype = EVENT_MODIFY_CAM_PARAM + 1;
    
    if ((event->param < 1) || (event->param > 4)) {
        std::string ss = "Param error !";
        LOG(WARNING, "Param error !");
        m.data.param = 1;
        strcpy(m.data.extra.sequence, ss.c_str());
        mq->send_message(M01, &m);
        return -1;
    }
    
    m.data.param = 0;
    m.data.extra.cam.camid = event->param;
    cv::VideoCapture *cam = util_get_cam_by_id(event->param);
    
    cam->set(cv::CAP_PROP_FRAME_WIDTH, m.data.extra.cam.width);
    cam->set(cv::CAP_PROP_FRAME_HEIGHT, m.data.extra.cam.height);
    cam->set(cv::CAP_PROP_FOCUS, m.data.extra.cam.F);
    cam->set(cv::CAP_PROP_IOS_DEVICE_EXPOSURE, m.data.extra.cam.ISO);
    cam->set(cv::CAP_PROP_ISO_SPEED, m.data.extra.cam.speed);

    mq->send_message(M01, &m);
    
    return 0;
}

int FruitFSM::action_start_size_auto_learning(Event *event){
    int catalog_num = event->param;
    if ((event->param < 0) || (event->param > 3))
        catalog_num = 3;

    util_delete_dir_content("/intelli/working/");
    util_delete_dir_content("/intelli/tracking/size/");

    learning = true;
    int ret = learning_start_size_auto_learning_thread(catalog_num);
    Message m;
    m.mtype = 200;
    m.data.ctype = EVENT_START_SIZE_AUTO + 1;
    if (ret == 0)
        m.data.param = 0;
    else {
        m.data.param = 1;
        strcpy(m.data.extra.sequence, "Start auto size learn thread failed !");
    }
    LOG(INFO, "Create auto size learning thread successfully !");
    mq->send_message(M01, &m);

    return 0;
}

int FruitFSM::action_get_size_auto_progress_image(Event *){
    Message m;
    m.mtype = 200;
    m.data.ctype = EVENT_GET_SIZE_AUTO_PROCESS_IMAGE + 1;
    m.data.param = 0;
    std::vector<std::string> fns;
    std::string ss1 = "/tracking/size/";
    util_get_dir_content(ss1, fns);
    if (fns.empty()) {
        m.data.param = 1;
        strcpy(m.data.extra.sequence, "File not exist !");
    }
    else {
        std::string ss2 = fns[fns.size() - 1];
        ss2 = ss2.substr(0, ss2.find_last_of('-'));
        strcpy(m.data.extra.sequence, ss1.append(ss2).c_str());
    }
    mq->send_message(M01, &m);

    return 0;
}

int FruitFSM::action_stop_size_auto_learning(Event *){
    learning = false;

    Message m;
    m.mtype = 200;
    m.data.ctype = EVENT_COMPLETE_SIZE_AUTO + 1;
    m.data.param = 0;
    mq->send_message(M01, &m);

    return 0;
}

int FruitFSM::action_learning_sal_return_learned_result_to_ui(Event *) {
    Message m;
    m.mtype = 200;
    m.data.ctype = EVENT_COMPLETE_SIZE_AUTO + 1;
    m.data.param = 0;

    m.data.extra.ls[0] = learned_size_model[0].ls;
    m.data.extra.ls[1] = learned_size_model[1].ls;
    m.data.extra.ls[2] = learned_size_model[2].ls;

    mq->send_message(M01, &m);

    return 0;
}

int FruitFSM::action_view_size_learning_sample(Event *event){
    Message m;
    m.mtype = 200;
    m.data.ctype = EVENT_VIEW_SIZE_SAMPLE + 1;
    if ((event->param < 1) || (event->param > 3) || (event->extra.addon < 1) || (event->extra.addon > 3)) {
        m.data.param = 1;
        strcpy(m.data.extra.sequence, "Parameter error !");
        mq->send_message(M01, &m);
        return -1;
    }
    
    std::string ss1;
    event->param==1?ss1="1":(event->param==2?ss1="/2":ss1="/3");
    std::string ss2;
    event->extra.addon==1?ss2="large":(event->extra.addon==2?ss2="middle":ss2="small");
    std::string dd = "/intelli/learning/size/";
    strcpy(m.data.extra.sequence, dd.append(ss1).append("/").append(ss2).c_str());
    mq->send_message(M01, &m);

    return 0;
}

int FruitFSM::action_save_size_learning_model(Event *){
    Message m;
    m.mtype = EVENT_SAVE_SIZE_LEARNED + 1;
    m.data.param = 0;

    learned_size_model[0].cam.camid = 1;
    learned_size_model[0].cam.speed = (int)cam1->get(cv::CAP_PROP_ISO_SPEED);
    learned_size_model[0].cam.ISO = (int)cam1->get(cv::CAP_PROP_IOS_DEVICE_EXPOSURE);
    learned_size_model[0].cam.F = (float)cam1->get(cv::CAP_PROP_FOCUS);
    learned_size_model[0].cam.width = (int)cam1->get(cv::CAP_PROP_FRAME_WIDTH);
    learned_size_model[0].cam.height = (int)cam1->get(cv::CAP_PROP_FRAME_HEIGHT);

    learned_size_model[1].cam.camid = 2;
    learned_size_model[1].cam.speed = (int)cam2->get(cv::CAP_PROP_ISO_SPEED);
    learned_size_model[1].cam.ISO = (int)cam2->get(cv::CAP_PROP_IOS_DEVICE_EXPOSURE);
    learned_size_model[1].cam.F = (float)cam2->get(cv::CAP_PROP_FOCUS);
    learned_size_model[1].cam.width = (int)cam2->get(cv::CAP_PROP_FRAME_WIDTH);
    learned_size_model[1].cam.height = (int)cam2->get(cv::CAP_PROP_FRAME_HEIGHT);

    learned_size_model[2].cam.camid = 3;
    learned_size_model[2].cam.speed = (int)cam3->get(cv::CAP_PROP_ISO_SPEED);
    learned_size_model[2].cam.ISO = (int)cam3->get(cv::CAP_PROP_IOS_DEVICE_EXPOSURE);
    learned_size_model[2].cam.F = (float)cam3->get(cv::CAP_PROP_FOCUS);
    learned_size_model[2].cam.width = (int)cam3->get(cv::CAP_PROP_FRAME_WIDTH);
    learned_size_model[2].cam.height = (int)cam3->get(cv::CAP_PROP_FRAME_HEIGHT);

    m.data.extra.lsm[0] = learned_size_model[0];
    m.data.extra.lsm[1] = learned_size_model[1];
    m.data.extra.lsm[2] = learned_size_model[2];

    mq->send_message(M01, &m);

    return 0;
}

int FruitFSM::action_start_semi_size_learning(Event *event){
    Message m;
    m.mtype = 200;
    m.data.ctype = EVENT_START_SIZE_SEMI + 1;
    m.data.param = 0;

    int size = event->param;
    if ((size < 1) || (size > 3)) {
        m.data.param = 1;
        strcpy(m.data.extra.sequence, "Parameter error !");
        mq->send_message(M01, &m);
        return -1;
    }

    util_delete_dir_content("/intelli/working/");
    util_delete_dir_content("/intelli/tracking/size/");

    learning = true;
    int ret = learning_start_size_semi_learning_thread(size);
    if (ret == 0)
        m.data.param = 0;
    else {
        m.data.param = 1;
        strcpy(m.data.extra.sequence, "Start semi size learn thread failed !");
    }
    LOG(INFO, "Create semi size learning thread successfully !");
    mq->send_message(M01, &m);

    return 0;
}

int FruitFSM::action_stop_semi_size_learning(Event *){
    learning = false;

    Message m;
    m.mtype = 200;
    m.data.ctype = EVENT_COMPLETE_SIZE_SEMI + 1;
    m.data.param = 0;
    mq->send_message(M01, &m);

    return 0;
}

int FruitFSM::action_learning_ssl_return_learned_result_to_ui(Event *event) {
    Message m;
    m.mtype = 200;
    m.data.ctype = EVENT_COMPLETE_SIZE_SEMI + 1;
    m.data.param = 0;

    int size = event->param;
    m.data.extra.ss.category = size;
    if (size == 1) {  //large
        m.data.extra.ss.cam01 = learned_size_model[0].ls.large;
        m.data.extra.ss.cam02 = learned_size_model[1].ls.large;
        m.data.extra.ss.cam03 = learned_size_model[2].ls.large;
    } else if (size == 2)  {  //middle
        m.data.extra.ss.cam01 = learned_size_model[0].ls.middle;
        m.data.extra.ss.cam02 = learned_size_model[1].ls.middle;
        m.data.extra.ss.cam03 = learned_size_model[2].ls.middle;
    } else {
        m.data.extra.ss.cam01 = learned_size_model[0].ls.small;
        m.data.extra.ss.cam02 = learned_size_model[1].ls.small;
        m.data.extra.ss.cam03 = learned_size_model[2].ls.small;
    }
    mq->send_message(M01, &m);

    return 0;
}

int FruitFSM::action_start_sugar_annotation(Event *event){
    Message m;
    m.mtype = 200;
    m.data.ctype = EVENT_START_SUGAR_ANN + 1;
    m.data.param = 0;

    int catalog_num = event->param;
    if ((event->param < 1) || (event->param > 2))
        catalog_num = 2;

    util_delete_dir_content("/intelli/working/");
    util_delete_dir_content("/intelli/tracking/sugar/");

    learning = true;
    sugar_ann_nirid_to_sugar.clear();

    int ret = learning_start_sugar_ann_thread(catalog_num);
    if (ret == 0) {
        m.data.param = 0;
        m.data.extra.sa.serial = 444;
    }
    else {
        m.data.param = 1;
        strcpy(m.data.extra.sequence, "Start sugar annotation thread failed !");
    }
    LOG(INFO, "Create sugar annotation thread successfully !");
    mq->send_message(M01, &m);

    return 0;
}

int FruitFSM::action_get_next_nir_image_and_set_previous_nir_sugar(Event *event){
    Message m;
    m.mtype = 200;
    m.data.ctype = EVENT_SUGAR_NEXT_PREVIOUS_VALUE + 1;
    m.data.param = 0;

    long nirid = event->extra.sa.nirid;
    if (nirid != -1) {
        float sugar = event->extra.sa.sugar;
        auto iter = sugar_ann_nirid_to_sugar.find(nirid);
        if(iter != sugar_ann_nirid_to_sugar.end()) {
            iter->second = sugar;
            char s1[128];
            sprintf(s1, "NIR = %ld annotated !", iter->first);
            LOG(INFO, s1);
        }
        else {
            m.data.param = 1;
            std::string ss = "Something wrong with sugar annotation !";
            strcpy(m.data.extra.sequence, ss.c_str());
            mq->send_message(M01, &m);
            LOG(ERROR, ss);
            return -1;
        }
    }

    std::vector<std::string> fns;
    util_get_dir_content("/intelli/working/", fns);
    if (fns.empty()) {
        m.data.param = 1;
        strcpy(m.data.extra.sequence, "Not ready !");
        mq->send_message(M01, &m);
    }
    else {
        std::string fn = fns.at(0);
        std::string sdir = "/intelli/working/";
        std::string ddir = "/intelli/learning/sugar/";
        util_copy_file(sdir, fn, ddir);
        remove((sdir+fn).c_str());
        sugar_ann_nirid_to_sugar.insert(std::pair<long, float>(nirid, 0));

        fn = fn.substr(0, fn.find_last_of('.'));
        nirid = std::stol(fn);
        m.data.extra.sa.nirid = nirid;
        m.data.extra.sa.serial = 444;
        strcpy(m.data.extra.sa.sugar_img, ddir.c_str());
        m.data.param = 0;
        mq->send_message(M01, &m);
    }

    return 0;
}

int FruitFSM::action_stop_sugar_annotation(Event *){
    learning = false;

    Message m;
    m.mtype = 200;
    m.data.ctype = EVENT_STOP_SUGAR_ANN + 1;
    m.data.param = 0;
    mq->send_message(M01, &m);

    return 0;
}

int FruitFSM::action_save_sugar_annotation(Event *){
    Message m;
    m.mtype = 200;
    m.data.ctype = EVENT_SAVE_SUGAR_ANN + 1;

    std::ofstream ofs("/intelli/learning/sugar/mapping.csv");
    if (ofs.is_open()) {
        for(auto item : sugar_ann_nirid_to_sugar) {
            ofs << item.first << "," << item.second << std::endl;
        }
        ofs.close();

        m.data.param = 0;
        strcpy(m.data.extra.sequence, "/intelli/learning/sugar/");
        mq->send_message(M01, &m);
    }
    else {
        m.data.param = 1;
        strcpy(m.data.extra.sequence, "Can not create CSV file !");
        mq->send_message(M01, &m);
    }

    return 0;
}

int FruitFSM::action_start_sugar_learning(Event *){
    Message m;
    m.mtype = 200;
    m.data.ctype = EVENT_START_SUGAR_LEARNING + 1;

    std::vector<std::string> fns;
    util_get_dir_content("/intelli/learning/sugar/", fns);
    if (fns.empty()) {
        m.data.param = 1;
        strcpy(m.data.extra.sequence, "Annotation does not exist !");
        mq->send_message(M01, &m);
        return -1;
    }

    int ret = learning_start_sugar_learning_thread();
    if (ret == 0)
        m.data.param = 0;
    else {
        m.data.param = 1;
        strcpy(m.data.extra.sequence, "Start sugar learning thread failed !");
    }
    LOG(INFO, "Create sugar learning thread successfully !");
    mq->send_message(M01, &m);

    return 0;
}

int FruitFSM::action_query_sugar_learning_progress(Event *){
    Message m;
    m.mtype = 200;
    m.data.ctype = EVENT_SUGAR_QUERY_LEARNING_PROGRESS + 1;
    m.data.param = 0;
    m.data.extra.addon = sugar_learning_progress_in_percent;
    mq->send_message(M01, &m);

    return 0;
}

int FruitFSM::action_save_sugar_learned_model(Event *){
    Message m;
    m.mtype = 200;
    m.data.ctype = EVENT_SAVE_SUGAR_LEARNED + 1;

    if (sugar_learning_progress_in_percent < 100) {
        m.data.param = 1;
        strcpy(m.data.extra.sequence, "Sugar learning does not finish !");
        mq->send_message(M01, &m);
        return -1;
    }
    else {
        //save model
        m.data.param = 0;
        mq->send_message(M01, &m);
    }

    return 0;
}

int FruitFSM::action_cancel_sugar_learning(Event *){
    pthread_cancel(sugar_learning_thread_id);
    sugar_learning_thread_id = -1;

    Message m;
    m.mtype = 200;
    m.data.ctype = EVENT_CANCEL_SUGAR_LEARNING + 1;
    m.data.param = 0;
    mq->send_message(M01, &m);

    return 0;
}

int FruitFSM::action_load_size_model(Event *event){
    std::string path = event->extra.sequence;
    std::ifstream fin(path.c_str());
    if (!fin.good()) {
        LOG(ERROR, "Cannot open size model failed !");
        fin.close();
        return -1;
    }
    
    neb::CJsonObject json;
    std::stringstream ss;
    ss << fin.rdbuf();
    if (!json.Parse(ss.str())) {
        LOG(ERROR, "Parse json error in size model file !");
        fin.close();
        return -1;
    }

    int ivalue;
    for(int i=0; i<3; i++) {
        json["cams"][i].Get("camid", ivalue);
        if ((ivalue < 1) || (ivalue > 3)) {
            LOG(ERROR, "Size model parameter error !");
            fin.close();
            return -1;
        }
        loaded_size_model[ivalue - 1].cam.camid = ivalue - 1;
        json["cams"][i].Get("width", loaded_size_model[ivalue - 1].cam.width);
        json["cams"][i].Get("height", loaded_size_model[ivalue - 1].cam.height);
        json["cams"][i].Get("F", loaded_size_model[ivalue - 1].cam.F);
        json["cams"][i].Get("speed", loaded_size_model[ivalue - 1].cam.speed);
        json["cams"][i].Get("ISO", loaded_size_model[ivalue - 1].cam.ISO);

        json["model"][i].Get("camid", ivalue);
        if ((ivalue < 1) || (ivalue > 3)) {
            LOG(ERROR, "Size model parameter error !");
            fin.close();
            return -1;
        }
        loaded_size_model[ivalue - 1].ls.camid = ivalue - 1;
        json["ls"][i].Get("large", loaded_size_model[ivalue - 1].ls.large);
        json["ls"][i].Get("middle", loaded_size_model[ivalue - 1].ls.middle);
        json["ls"][i].Get("small", loaded_size_model[ivalue - 1].ls.small);
    }
    size_model_loaded = true;
    fin.close();

    return 0;
}

int FruitFSM::action_load_sugar_model(Event *){
    return 0;
}

int FruitFSM::action_start_sorting(Event *event){
    Message m;
    m.mtype = 200;
    m.data.ctype = EVENT_START_SORTING + 1;

    int size_and_sugar = event->param;
    if ((size_and_sugar < 1) || (size_and_sugar > 3)) {
        std::string s1 = "Parameter error !";
        LOG(ERROR, s1);
        m.data.param = 1;
        strcpy(m.data.extra.sequence, s1.c_str());
        mq->send_message(M01, &m);
        return -1;
    }
    if (((size_and_sugar == 1) && (!size_model_loaded))  ||
        ((size_and_sugar == 2) && (!sugar_model_loaded)) ||
        (((size_and_sugar == 3) && (!size_model_loaded)) || (!sugar_model_loaded))){
        std::string s1 = "Parameter's corresponding model not loaded !";
        LOG(ERROR, s1);
        m.data.param = 1;
        strcpy(m.data.extra.sequence, s1.c_str());
        mq->send_message(M01, &m);
        return -1;
    }

    util_delete_dir_content("/intelli/working/");
    util_delete_dir_content("/intelli/tracking/size/");
    util_delete_dir_content("/intelli/tracking/sugar/");

    std::string ss;
    util_get_current_second_time_in_string(ss); //return format like: 2021-03-10-11-23-45
    ss.insert(0, "/intelli/output/").append("/");
    if (util_create_multi_dirs(ss) < 0) {
        std::string s1 = "Create directory error !";
        LOG(ERROR, s1);
        m.data.param = 1;
        strcpy(m.data.extra.sequence, s1.c_str());
        mq->send_message(M01, &m);
        return -1;
    }

    if (size_and_sugar == 1) {  //only by size
        util_create_multi_dirs(ss + "model/");
        util_create_multi_dirs(ss + "data/" + "1/");
        util_create_multi_dirs(ss + "data/" + "2/");
        util_create_multi_dirs(ss + "data/" + "3/");
    }else if (size_and_sugar == 2) {  //only by sugar
        util_create_multi_dirs(ss + "model/");
        util_create_multi_dirs(ss + "data/" + "1/");
        util_create_multi_dirs(ss + "data/" + "2/");
    }else { //by size and sugar
        util_create_multi_dirs(ss + "model/");
        util_create_multi_dirs(ss + "data/" + "1/");
        util_create_multi_dirs(ss + "data/" + "2/");
        util_create_multi_dirs(ss + "data/" + "3/");
        util_create_multi_dirs(ss + "data/" + "4/");
        util_create_multi_dirs(ss + "data/" + "5/");
        util_create_multi_dirs(ss + "data/" + "6/");
        util_create_multi_dirs(ss + "data/" + "7/");
    }

    int ret = start_sorting_thread(size_and_sugar);
    if (ret == 0) {
        m.data.param = 0;
        m.data.extra.addon = 333;
    }
    else {
        m.data.param = 1;
        strcpy(m.data.extra.sequence, "Start sorting thread failed !");
        util_delete_dir_content(ss.c_str());
        rmdir(ss.c_str());
    }
    LOG(INFO, "Create sorting thread successfully !");
    mq->send_message(M01, &m);

    return 0;
}

int FruitFSM::action_view_sorting_process_image(Event *){
    Message m;
    m.mtype = 200;
    m.data.ctype = EVENT_VIEW_SORTING_PRECESS_IMAGE + 1;
    m.data.param = 0;
    std::string dd = "/intelli/learning/";  //size image in "size" subdir, sugar image in "sugar" subdir
    strcpy(m.data.extra.sequence, dd.c_str());
    mq->send_message(M01, &m);

    return 0;
}

int FruitFSM::action_view_sorting_statistics(Event *){
    Message m;
    m.mtype = 200;
    m.data.ctype = EVENT_VIEW_SORTING_STATISTICS + 1;
    m.data.param = 0;
    m.data.extra.stat = statistics;
    mq->send_message(M01, &m);

    return 0;
}

int FruitFSM::action_pause_sorting(Event *){
    sorting = false;
    pthread_cancel(addon_sugar_thread_id);
    return 0;
}

int FruitFSM::action_get_history_sorting_data(Event *){
    Message m;
    m.mtype = 200;
    m.data.ctype = EVENT_GET_HISTORY_SORTED_LIST + 1;
    m.data.param = 0;
    strcpy(m.data.extra.sequence, "/intelli/output/");
    mq->send_message(M01, &m);

    return 0;
}

int FruitFSM::action_view_history_statistics(Event *){
    Message m;
    m.mtype = 200;
    m.data.ctype = EVENT_VIEW_HISTORY_STATISTICS + 1;
    m.data.param = 0;
    std::string dd = "/intelli/output/";
    dd.append(m.data.extra.sequence);
    strcpy(m.data.extra.sequence, dd.c_str());
    mq->send_message(M01, &m);

    return 0;
}

int FruitFSM::action_delete_history_data(Event *){
    Message m;
    m.mtype = 200;
    m.data.ctype = EVENT_DELETE_HISTORY + 1;
    m.data.param = 0;
    std::string dd = "/intelli/output/";
    dd.append(m.data.extra.sequence);
    util_delete_dir_content(dd.c_str());
    rmdir(dd.c_str());
    m.data.param = 0;
    mq->send_message(M01, &m);

    return 0;
}

int FruitFSM::action_put_event_back_to_queue(Event *event){
    Message m;
    
    m.mtype = 200;
    m.data = *event;
    mq->send_message(M02, &m);
    
    return 0;
}
